using System;
using System.Runtime.InteropServices;

namespace NTrace
{
  [StructLayout(LayoutKind.Explicit, Size=48, Pack=1)]
  internal struct EventTraceHeader
  {
    /// <summary>
    /// <para>Total number of bytes of the event. Size includes the size of the header structure, plus the size of any event-specific data appended to the header. </para>
    /// <para>On input, the size must be the lesser of 64K (the largest possible event you can specify) and the size of the event tracing session's buffer minus the size of the EVENT_TRACE_HEADER structure.</para>
    /// </summary>
    [FieldOffset(0)]
    public ushort Size;

    /// <summary>
    /// Reserved.
    /// </summary>`
    [FieldOffset(2)]
    private ushort FieldTypeFlags;
    
    /// <summary>
    /// Reserved.
    /// </summary>
    [FieldOffset(2)]
    private byte HeaderType;
    
    /// <summary>
    /// Reserved.
    /// </summary>
    [FieldOffset(3)]
    private byte MarkerFlags;

    /// <summary>
    /// This is a roll-up of the members of Class. The low-order byte contains the Type, the next byte contains the Level, and the last two bytes contain the version. 
    /// </summary>
    [FieldOffset(4)]
    public uint Version;
    
    /// <summary>
    /// The type of event.
    /// </summary>
    [FieldOffset(4)]
    public EventClassType ClassType;
    
    /// <summary>
    /// The severity level used to generate the event.
    /// </summary>
    [FieldOffset(5)]
    public EventClassLevel ClassLevel;
    
    /// <summary>
    /// Indicates the version of the event trace class that you are using to log the event. Used by MOF providers.
    /// </summary>
    [FieldOffset(6)]
    public ushort ClassVersion;
    
    /// <summary>
    /// The thread that generated the event.
    /// </summary>
    [FieldOffset(8)]
    public uint ThreadId;
    
    /// <summary>
    /// The process that generated the event.
    /// </summary>
    [FieldOffset(12)]
    public uint ProcessId;
    
    /// <summary>
    /// On output, contains the time the event occurred.
    /// </summary>
    [FieldOffset(16)]
    public Int64 TimeStamp;
    
    /// <summary>
    /// Event trace class GUID. You can use the class GUID to identify a category of events and the Class.Type member to identify an event within the category of events.
    /// </summary>
    [FieldOffset(24)]
    public Guid Guid;
    
    [FieldOffset(24)]
    private UInt64 GuidPtr;
    
    /// <summary>
    /// Reserved.
    /// </summary>
    [FieldOffset(40)]
    public uint ClientContext;
    
    /// <summary>
    /// Trace flags
    /// </summary>
    [FieldOffset(44)]
    public TraceHeaderFlags Flags;
    
    /// <summary>
    /// Elapsed execution time for kernel-mode instructions, in CPU time units.
    /// </summary>
    [FieldOffset(40)]
    public uint KernelTime;
    
    /// <summary>
    /// Elapsed execution time for user-mode instructions, in CPU time units.
    /// </summary>
    [FieldOffset(44)]
    public uint UserTime;
    
    /// <summary>
    /// For private sessions, the elapsed execution time for user-mode instructions, in CPU ticks.
    /// </summary>
    [FieldOffset(40)]
    public UInt64 ProcessorTime;
  }
/*
  internal class EventTraceHeaderMarshaler : ICustomMarshaler
  {
    private static System.Collections.Generic.Dictionary<String, EventTraceHeaderMarshaler> instances =
            new System.Collections.Generic.Dictionary<string, EventTraceHeaderMarshaler>();

    private EventTraceHeaderMarshaler()
    {
    }

    public static ICustomMarshaler GetInstance(String cookie)
    {
      if (!EventTraceHeaderMarshaler.instances.ContainsKey(cookie))
      {
        EventTraceHeaderMarshaler temp = new EventTraceHeaderMarshaler();
        EventTraceHeaderMarshaler.instances[cookie] = temp;
      }
      return EventTraceHeaderMarshaler.instances[cookie];
    }

    public void CleanUpManagedData(object ManagedObj)
    {

    }

    public void CleanUpNativeData(IntPtr pNativeData)
    {

    }

    public int GetNativeDataSize()
    {
      return 0;
    }

    public IntPtr MarshalManagedToNative(object ManagedObj)
    {
      return IntPtr.Zero;
    }

    public object MarshalNativeToManaged(IntPtr pNativeData)
    {
      EventTraceHeader output = null;
      // Allocate memory to hold the structure

      // Write Size as a short (+offset 2 bytes)
      // Write 0 as a short (+offset 2 bytes)
      // Write the Version as an int (we can use 0) (+offset 4 bytes)
      // Write the thread ID as an int (we can use 0) (+offset 4 bytes)
      // Write the process ID as an int (we can use 0) (+offset 4 bytes)
      // Write the timestamp ID as an int64 (we can use 0) (+offset 8 bytes)
      // Write the message file Guid (+offset 16 bytes)
      // Write the client context as an int (we can use 0) (+offset 4 bytes)
      // Write the flags as an int (TraceHeaderFlags.Default | TraceHeaderFlags.DataAttached) (+offset 4 bytes)
      return output;
    }
  }
 */
}
